package com.tuzhi.base.jpa.domain;

import com.tuzhi.base.function.SFunction;
import com.tuzhi.base.jpa.enums.AndOrOperate;
import com.tuzhi.base.jpa.enums.QueryTypeEnum;
import com.tuzhi.base.jpa.enums.SortOrderEnum;
import com.tuzhi.base.util.PropertyUtil;
import com.tuzhi.common.exception.BusinessException;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 功能说明：
 *
 * @author abu
 * @version 1.1.0
 * @date 2023/3/5
 */
public class QueryFilter<T> {

    private WhereConditionBO whereConditionBO = null;

    public static QueryFilter getInstantiation() {
        return new QueryFilter();
    }

    private QueryFilter() {
        whereConditionBO = new WhereConditionBO();
        whereConditionBO.setQueryList(new ArrayList<>());
        whereConditionBO.setSortList(new ArrayList<>());
    }

    private void addQueryFilter(SFunction<? super T, ? > propertyName, AndOrOperate andOrOperate, Object filterValue, QueryTypeEnum queryType) {
        QueryConditionBO queryConditionBO = new QueryConditionBO();
        String propertyNameStr = PropertyUtil.getFieldName(propertyName);
        queryConditionBO.setPropertyName(propertyNameStr);
        queryConditionBO.setAndOrOperate(andOrOperate);
        switch (queryType) {
            case in:
            case notIn:
            case between:
                queryConditionBO.setObjList((List) filterValue);
                break;
            default:
                queryConditionBO.setObjValue(filterValue);
                break;
        }
        queryConditionBO.setQueryTypeEnum(queryType);
        whereConditionBO.getQueryList().add(queryConditionBO);
    }

    private void addSort(SFunction<? super T, ? > propertyName, SortOrderEnum sortOrderEnum) {
        SortConditionBO sortConditionBO = new SortConditionBO();
        String propertyNameStr = PropertyUtil.getFieldName(propertyName);
        sortConditionBO.setPropertyName(propertyNameStr);
        sortConditionBO.setSortOrderEnum(sortOrderEnum);
        whereConditionBO.getSortList().add(sortConditionBO);
    }

    public QueryFilter sortDesc(SFunction<? super T, ? > propertyName) {
        addSort(propertyName, SortOrderEnum.DESC);
        return this;
    }

    public QueryFilter sortAce(SFunction<? super T, ? > propertyName) {
        addSort(propertyName, SortOrderEnum.ACE);
        return this;
    }


    /**
     * 指定属性名与属性值作and的nlike查询
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter nlk(SFunction<? super T, ? > propertyName, Object filterValue) {
        addQueryFilter(propertyName, AndOrOperate.and, filterValue, QueryTypeEnum.notLike);
        return this;
    }

    /**
     * 指定属性名与属性值作and的nlike查询
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter lk(SFunction<? super T, ? > propertyName, Object filterValue) {
        addQueryFilter(propertyName, AndOrOperate.and, filterValue, QueryTypeEnum.like);
        return this;
    }

    /**
     * 指定属性名与属性值作and的eq查询
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter eq(SFunction<? super T, ? > propertyName, Object filterValue) {
        addQueryFilter(propertyName, AndOrOperate.and, filterValue, QueryTypeEnum.equal);
        return this;
    }

    /**
     * 指定属性名与属性值作and neq查询
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter neq(SFunction<? super T, ?> propertyName, Object filterValue) {
        neq(propertyName, filterValue, AndOrOperate.and);
        return this;
    }

    /**
     * 指定属性名与属性值作  neq查询
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter neq(SFunction<? super T, ? > propertyName, Object filterValue, AndOrOperate andOrOperate) {
        addQueryFilter(propertyName, andOrOperate, filterValue, QueryTypeEnum.notEqual);
        return this;
    }

    /**
     * 对指定的属性，作日期范围查询
     *
     * @param propertyName 属性名
     * @param beginDate    开始日期
     * @param endDate      结束日期
     * @return
     */
    public QueryFilter bwn(SFunction<? super T, ?> propertyName, Date beginDate, Date endDate, AndOrOperate andOrOperate) {
        List<Date> bwnDates = new ArrayList<>();
        bwnDates.add(beginDate);
        bwnDates.add(endDate);
        andOrOperate = andOrOperate != null ? andOrOperate : AndOrOperate.and;
        addQueryFilter(propertyName, andOrOperate, bwnDates, QueryTypeEnum.between);
        return this;
    }

    /**
     * 指定属性名，属性值集合，作in 查找记录
     *
     * @param propertyName
     * @param value
     * @param andOrOperate
     * @return
     */
    public <E> QueryFilter in(SFunction<? super T, ? > propertyName, List<E> value, AndOrOperate andOrOperate) {
        andOrOperate = andOrOperate != null ? andOrOperate : AndOrOperate.and;
        addQueryFilter(propertyName, andOrOperate, value, QueryTypeEnum.in);
        return this;
    }

    public <E> QueryFilter in(SFunction<? super T, ?> propertyName, List<E> value) {
        return in(propertyName, value, AndOrOperate.and);
    }

    /**
     * 大于 >
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter gt(SFunction<? super T, ?> propertyName, Object filterValue) {
        addQueryFilter(propertyName, AndOrOperate.and, filterValue, QueryTypeEnum.gt);
        return this;
    }

    /**
     * 小于 <
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter lt(SFunction<? super T, ? > propertyName, Object filterValue) {
        addQueryFilter(propertyName, AndOrOperate.and, filterValue, QueryTypeEnum.lt);
        return this;
    }

    /**
     * 小于 <
     *
     * @param propertyName
     * @param filterValue
     * @param filterValue
     * @return
     */
    public QueryFilter lt(SFunction<? super T, ? > propertyName, Object filterValue,AndOrOperate andOrOperate) {
        addQueryFilter(propertyName, andOrOperate, filterValue, QueryTypeEnum.lt);
        return this;
    }
    /**
     * 大于等于 >=
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter gte(SFunction<? super T, ? > propertyName, Object filterValue) {
        addQueryFilter(propertyName, AndOrOperate.and, filterValue, QueryTypeEnum.gt);
        return this;
    }

    /**
     * 小于等于<=
     *
     * @param propertyName
     * @param filterValue
     * @return
     */
    public QueryFilter lte(SFunction<? super T, ? > propertyName, Object filterValue) {
        addQueryFilter(propertyName, AndOrOperate.and, filterValue, QueryTypeEnum.le);
        return this;
    }
    /**
     * 小于等于<=
     *
     * @param propertyName
     * @param filterValue
     * @param andOrOperate
     * @return
     */
    public QueryFilter lte(SFunction<? super T, ? > propertyName, Object filterValue,AndOrOperate andOrOperate) {
        addQueryFilter(propertyName, andOrOperate, filterValue, QueryTypeEnum.le);
        return this;
    }



    public WhereConditionBO buildQueryConditionBO() {
        if (whereConditionBO == null) {
            throw new BusinessException("请先调用 getInstantiation ");
        }
        return whereConditionBO;
    }

    public static void main(String[] args) {


    }

}
